#include "ResourceCache.h"
namespace re
{
	namespace io
	{
		ResourceCache::ResourceCache()
		{
			ResourceUnpackerPtr direct_loader(new DirectLoader);
			std::wstring fmt;
			fmt = L".sdf";
			AddResourceUnpacker(fmt, direct_loader);
			fmt = L".pdb";
			AddResourceUnpacker(fmt, direct_loader);
		}
		ResourceCache::~ResourceCache()
		{
		}
		ResourceHandlePtr ResourceCache::GetResource(const std::wstring & filename)
		{
			ResourceHandlePtr handle = FindResource(filename);
			if(handle == ResourceHandlePtr())
			{
				return LoadResource(filename);
			}else
			{
				return handle;
			}
		}
		ResourceHandlePtr ResourceCache::LoadResource(const std::wstring & filename)
		{
			U32 format_pos = filename.find_last_of(L".");
			if(format_pos == filename.npos)
			{
				assert(0 && "Invalid file path.");
				return ResourceHandlePtr();
			}
			ResourceUnpackerMap::iterator unpacker_iterator = unpackers_.find(filename.substr(format_pos));
			if(unpacker_iterator == unpackers_.end())
			{
				assert(0 && "No loader can handle this request!");
				return ResourceHandlePtr();
			}

			char * buffer = NULL;
			U32 size = unpacker_iterator->second->LoadFile(filename,0, &buffer);
			if(buffer == NULL)
			{
				assert(0 && "Failed to fill the buffer. (This the error you may get if you ask for un invalid file)");
				return ResourceHandlePtr();
			}
			ResourceHandlePtr handle(new ResourceHandle(buffer, size));
			handles_[filename] = handle;
			return handle;
		}
		ResourceHandlePtr ResourceCache::FindResource(const std::wstring & filename)
		{
			ResourceHandleMap::iterator i = handles_.find(filename);
			if(i != handles_.end())
			{
				return i->second;
			}
			return ResourceHandlePtr();
		}
		bool ResourceCache::AddResourceUnpacker(std::wstring & format,ResourceUnpackerPtr loader)
		{
			ResourceUnpackerMap::iterator i = unpackers_.find(format);
			ResourceUnpackerMap::iterator end = unpackers_.end();
			if(i != end)
			{
				assert(0 && "Attempt to insert the second listener for the same format twice!");
				return false;
			}
			unpackers_.insert(make_pair(format, loader));
			return true;
		}
		bool ResourceCache::RemoveResourceUnpacker(ResourceUnpackerPtr loader)
		{
			ResourceUnpackerMap::iterator i = unpackers_.begin();
			ResourceUnpackerMap::iterator end = unpackers_.end();
			while(i != end)
			{
				if(loader == (*i).second)
				{
					unpackers_.erase(i);
					return true;
				}
				++i;
			}
			return false;

		}

		bool ResourceCache::ReleaseCache()
		{
			handles_.clear();
			return true;
		}
	}
}